package com.example.springboottools.sap;

import cn.hutool.json.JSON;
import cn.hutool.json.JSONUtil;
import com.sap.conn.jco.*;
import com.sap.conn.jco.ext.DestinationDataProvider;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.FileOutputStream;
import java.util.*;

public class SAPClient {
	
	static Logger logger = LoggerFactory.getLogger(SAPClient.class);
	
	static PropertyUtil propertyUtil = new PropertyUtil("sapjco.dev.properties");
	
	public static String ABAP_AS = "ABAP_AS_WITHOUT_POOL";
	static  JCoDestination destination1 = null;
	static {
		Properties connectProperties = new Properties();
		connectProperties.setProperty(DestinationDataProvider.JCO_ASHOST, propertyUtil.getPropertyStr("jco.ashost"));
		connectProperties.setProperty(DestinationDataProvider.JCO_SYSNR, propertyUtil.getPropertyStr("jco.sysnr"));
		connectProperties.setProperty(DestinationDataProvider.JCO_CLIENT, propertyUtil.getPropertyStr("jco.client"));
		connectProperties.setProperty(DestinationDataProvider.JCO_USER, propertyUtil.getPropertyStr("jco.user"));
		// Must use Upper case for password, otherwise, SAP server will report
		// password is incorrect.
		connectProperties.setProperty(DestinationDataProvider.JCO_PASSWD, propertyUtil.getPropertyStr("jco.passwd"));
		connectProperties.setProperty(DestinationDataProvider.JCO_LANG, propertyUtil.getPropertyStr("jco.lang"));
		//connectProperties.setProperty(DestinationDataProvider.JCO_MAX_GET_TIME, "");
		createDataFile(ABAP_AS, "jcoDestination", connectProperties);
        try {
             destination1 = JCoDestinationManager.getDestination(ABAP_AS);
        } catch (JCoException e) {
            throw new RuntimeException(e);
        }
    }

	// Creates a connection configuration file based on parameters given above
	static void createDataFile(String name, String suffix, Properties properties) {
		File cfg = new File(name + "." + suffix);
		//if (!cfg.exists()) {
			try {
				FileOutputStream fos = new FileOutputStream(cfg, false);
				properties.store(fos, "for sapjco properties !");
				fos.close();
			} catch (Exception e) {
				throw new RuntimeException("Unable to create the destination file " + cfg.getName(), e);
			}
		//}
	}

	public static Map<String, String> getSAPData(String Func,Map<String, String> inMap,List<String> outMsg) throws JCoException {
		JCoDestination destination = JCoDestinationManager.getDestination(ABAP_AS);
		logger.info("Attributes:");
		logger.info(destination.getAttributes().toString());
		logger.info("End Attributes!");
		
		
		JCoFunction function = destination.getRepository().getFunction(Func);
		if (function == null)
			throw new RuntimeException("STFC_CONNECTION not found in SAP.");
		
		for (Map.Entry<String, String> m : inMap.entrySet()) {
			function.getImportParameterList().setValue(m.getKey(), m.getValue());
		}
		
		
		try {
			function.execute(destination);
		} catch (AbapException e) {
			logger.info("SAP接口调用异常", e.getMessage());
			e.printStackTrace();
			return null;
		}
		
		Map<String, String> resMap = new HashMap<String,String>();
		
		for (String o : outMsg) {
			resMap.put(o, function.getExportParameterList().getString(o));
		}
		return resMap;
	}
	
	/**
	 * 
	 * @param Func
	 * @param inList
	 * @param keyMap （key是sap的字段名，value是实体字段名）
	 * @return
	 * @throws JCoException
	 */
	public static List<Map<String, String>> getSAPData(String Func,Map<String,List<Map<String, String>>> inMap,Map<String, Map<String, String>> keyMap,String SAPresTab) throws JCoException {
		JCoDestination destination = JCoDestinationManager.getDestination(ABAP_AS);
		logger.info("Attributes:");
		logger.info(destination.getAttributes().toString());
		logger.info("End Attributes!");
		
		JCoFunction function = destination.getRepository().getFunction(Func);//"ZRFC_SC_MM_VENDOR_CREATE"
		if (function == null)
			throw new RuntimeException("STFC_CONNECTION not found in SAP.");
		
		for(Map.Entry<String, Map<String, String>> t : keyMap.entrySet()){
			
			JCoTable table = function.getTableParameterList().getTable(t.getKey());
			int i = 0;
			for(Map<String, String> rowMap:inMap.get(t.getKey())){
				table.appendRow();
				table.setRow(i++);
				for(Map.Entry<String, String> m : t.getValue().entrySet()){
					table.setValue(m.getKey(), rowMap.get(m.getValue()));
				}			
			}
		}
		try {
			function.execute(destination);
		} catch (AbapException e) {
			logger.error("",e);
			return null;
		}
		List<Map<String, String>> outMsg = new ArrayList<Map<String,String>>();
		if(SAPresTab != null && !"".equals(SAPresTab)){
			JCoTable restab = function.getTableParameterList().getTable(SAPresTab);
			for (int y = 0; y < restab.getNumRows(); y++) {
				restab.setRow(y);
				Map<String, String> row = new HashMap<String, String>();
				JCoFieldIterator iterator = restab.getFieldIterator();
		        while (iterator.hasNextField()) {
		            JCoField recordField = iterator.nextField();
		            String fieldName=recordField.getName();
		            //Object  value=recordField.getValue();
		            String val_str=recordField.getString();
					row.put(fieldName, val_str);
		        }
				outMsg.add(row); 
			}
		}
		return outMsg;
	}
	/**
	 *推送sap发货状态
	 * @param Func
	 * @param
	 * @param keyMap （key是sap的字段名，value是实体字段名）
	 * @return
	 * @throws JCoException
	 */
	public static List<Map<String, String>> getSAPDeliveryData(String Func,Map<String,List<Map<String, String>>> inMap,Map<String, Map<String, String>> keyMap,String SAPresTab,List<String> outMsg11,Long businessType) throws Exception {
		//JCoDestination destination = JCoDestinationManager.getDestination(ABAP_AS);
		JCoDestination destination = destination1;
		logger.info("Attributes:");
		logger.info(destination.getAttributes().toString());
		logger.info("End Attributes!");
		JCoRepository repository = destination.getRepository();
		repository.clear();
		JCoFunction function = repository.getFunction(Func);//"ZRFC_SC_MM_VENDOR_CREATE"
		if (function == null)
			throw new RuntimeException("STFC_CONNECTION not found in SAP.");

		for(Map.Entry<String, Map<String, String>> t : keyMap.entrySet()){

			JCoTable table = function.getTableParameterList().getTable(t.getKey());
			int i = 0;
			for(Map<String, String> rowMap:inMap.get(t.getKey())){
				table.appendRow();
				table.setRow(i++);
				for(Map.Entry<String, String> m : t.getValue().entrySet()){
					/*if (PoStatusLogBusinessEnum.DELIVERY.getCode().equals(businessType)&&"STATUS".equals(m.getKey())){
						table.setValue(m.getKey(),businessType);
					}else {
						table.setValue(m.getKey(), rowMap.get(m.getValue()));
					}*/
//					if (StringUtils.isNotBlank(m.getKey())&&!m.getKey().equalsIgnoreCase("DELITWAY")){
//						table.setValue(m.getKey(), rowMap.get(m.getValue()));
//					}
					table.setValue(m.getKey(), rowMap.get(m.getValue()));
				}
			}
		}
		try {
			function.execute(destination);
		} catch (AbapException e) {
			logger.error("",e);
			return null;
		}
		List<Map<String, String>> outMsg = new ArrayList<Map<String,String>>();
		if(SAPresTab != null && !"".equals(SAPresTab)){
			JCoTable restab = function.getTableParameterList().getTable(SAPresTab);
			for (int y = 0; y < restab.getNumRows(); y++) {
				restab.setRow(y);
				Map<String, String> row = new HashMap<String, String>();
				JCoFieldIterator iterator = restab.getFieldIterator();
				while (iterator.hasNextField()) {
					JCoField recordField = iterator.nextField();
					String fieldName=recordField.getName();
					//Object  value=recordField.getValue();
					String val_str=recordField.getString();
					row.put(fieldName, val_str);
				}
				outMsg.add(row);
			}
		}else {
			Map<String,String> resMap=new HashMap<>();
			for (String o : outMsg11) {
				resMap.put(o, function.getExportParameterList().getString(o));
			}
			outMsg.add(resMap);
		}
		return outMsg;
	}
	/**
	 * 
	 * @param Func
	 * @param inList
	 * @param keyMap （key是sap的字段名，value是实体字段名）
	 * @return
	 * @throws JCoException
	 */
	public static Map<String, List<Map<String, String>>> getSAPData(String Func,Map<String,List<Map<String, String>>> inMap,Map<String, Map<String, String>> keyMap,List<String> SAPresTab) throws JCoException {
		JCoDestination destination = JCoDestinationManager.getDestination(ABAP_AS);
		logger.info("Attributes:");
		logger.info(destination.getAttributes().toString());
		logger.info("End Attributes!");
		
		JCoFunction function = destination.getRepository().getFunction(Func);//"ZRFC_SC_MM_VENDOR_CREATE"
		if (function == null)
			throw new RuntimeException("STFC_CONNECTION not found in SAP.");
		
		for(Map.Entry<String, Map<String, String>> t : keyMap.entrySet()){
			
			JCoTable table = function.getTableParameterList().getTable(t.getKey());
			int i = 0;
			for(Map<String, String> rowMap:inMap.get(t.getKey())){
				table.appendRow();
				table.setRow(i++);
				for(Map.Entry<String, String> m : t.getValue().entrySet()){
					table.setValue(m.getKey(), rowMap.get(m.getValue()));
				}			
			}
		}
		try {
			function.execute(destination);
		} catch (AbapException e) {
			logger.info("SAP接口调用异常", e.getMessage());
			e.printStackTrace();
			return null;
		}
		Map<String, List<Map<String, String>>> outMsg = new HashMap<String, List<Map<String,String>>>();
		if(SAPresTab != null && !SAPresTab.isEmpty()){
			for(String tabName : SAPresTab){
				List<Map<String, String>> Msg = new ArrayList<Map<String,String>>();
				JCoTable restab = function.getTableParameterList().getTable(tabName);
				for (int y = 0; y < restab.getNumRows(); y++) {
					restab.setRow(y);
					Map<String, String> row = new HashMap<String, String>();
					JCoFieldIterator iterator = restab.getFieldIterator();
			        while (iterator.hasNextField()) {
			            JCoField recordField = iterator.nextField();
			            String fieldName=recordField.getName();
			            //Object  value=recordField.getValue();
			            String val_str=recordField.getString();
						row.put(fieldName, val_str);
			        }
					Msg.add(row); 
				}
				outMsg.put(tabName, Msg);
			}
		}
		return outMsg;
	}

	public static void main(String[] args) {
		String func = "ZRFC_DELIVERY_STATUS_FVP";
		Map<String, List<Map<String, String>>> inMap = new HashMap<String, List<Map<String, String>>>();
		Map<String, Map<String, String>> keyMap = new HashMap<String, Map<String, String>>();
		List<Map<String, String>> deliveryList = new ArrayList<>();
		Map<String,String> map = new HashMap<>();
		map.put("EBELN","4507528792");
		map.put("DELITWAY","");
		map.put("STATUS","Y");
		inMap.put("IT_EBELN", deliveryList);
		deliveryList.add(map);
		keyMap.put("IT_EBELN", SAPDeliveryMap());
		List<String> outMsg = Arrays.asList("E_TYPE", "E_MESSAGE");
        try {
            List<Map<String, String>> sapDeliveryData = SAPClient.getSAPDeliveryData(func, inMap, keyMap, null, outMsg, 10L);

		} catch (Exception e) {
            throw new RuntimeException(e);
        }
    }

	public static Map<String, String> SAPDeliveryMap() {
		HashMap<String, String> deliveryMap = new HashMap<>();
		deliveryMap.put("EBELN", "EBELN");
		deliveryMap.put("STATUS", "STATUS");
		deliveryMap.put("DELITWAY", "DELITWAY");
		return deliveryMap;
	}
}
